package com.zjx.mhxykey.util;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class FastImageMatcher {
    private static final String TAG = "FastImageMatcher";
    private static final int SAMPLE_SIZE = 4; // 采样率，提高匹配速度

    /**
     * 使用特征点匹配查找所有相似子图位置
     * @param source 源图像
     * @param template 模板图像
     * @param threshold 相似度阈值(0-1)
     * @param minDistance 最小匹配间距
     * @return 匹配位置列表
     */
    public static List<Point> findMatches(Bitmap source, Bitmap template,
                                          float threshold, int minDistance) {
        List<Point> matches = new ArrayList<>();
        if (source == null || template == null) {
            Log.w(TAG, "输入图像不能为null");
            return matches;
        }

        try {
            // 1. 缩小图像尺寸提高效率
            Bitmap smallSource = resizeBitmap(source, source.getWidth()/SAMPLE_SIZE,
                    source.getHeight()/SAMPLE_SIZE);
            Bitmap smallTemplate = resizeBitmap(template, template.getWidth()/SAMPLE_SIZE,
                    template.getHeight()/SAMPLE_SIZE);

            // 2. 提取关键特征点
            int[][] sourceFeatures = extractFeatures(smallSource);
            int[][] templateFeatures = extractFeatures(smallTemplate);

            // 3. 粗匹配获取可能区域
            List<Point> roughMatches = findRoughMatches(sourceFeatures, templateFeatures,
                    smallSource.getWidth(),
                    smallTemplate.getWidth());

            // 4. 在原始图像上精确定位
            for (Point roughPoint : roughMatches) {
                int x = roughPoint.x * SAMPLE_SIZE;
                int y = roughPoint.y * SAMPLE_SIZE;

                // 在原图上验证
                if (x + template.getWidth() <= source.getWidth() &&
                        y + template.getHeight() <= source.getHeight()) {

                    Bitmap subArea = Bitmap.createBitmap(source, x, y,
                            template.getWidth(),
                            template.getHeight());
                    double similarity = compareByHistogram(subArea, template);

                    if (similarity >= threshold) {
                        // 检查是否与已找到的点太近
                        boolean isNewMatch = true;
                        for (Point p : matches) {
                            if (Math.abs(x - p.x) < minDistance &&
                                    Math.abs(y - p.y) < minDistance) {
                                isNewMatch = false;
                                break;
                            }
                        }
                        if (isNewMatch) {
                            matches.add(new Point(x, y));
                        }
                    }
                }
            }

            // 回收临时bitmap
            smallSource.recycle();
            smallTemplate.recycle();

        } catch (OutOfMemoryError e) {
            Log.e(TAG, "内存不足，请减小采样率或图像尺寸", e);
        }

        return matches;
    }

    /**
     * 提取图像特征点（简化版）
     */
    private static int[][] extractFeatures(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[][] features = new int[width][height];

        // 转换为灰度并提取边缘特征
        for (int y = 1; y < height-1; y++) {
            for (int x = 1; x < width-1; x++) {
                // Sobel边缘检测简化版
                int pixel = getGrayValue(bitmap.getPixel(x, y));
                int gx = getGrayValue(bitmap.getPixel(x+1, y)) - pixel;
                int gy = getGrayValue(bitmap.getPixel(x, y+1)) - pixel;
                features[x][y] = (int) Math.sqrt(gx*gx + gy*gy);
            }
        }
        return features;
    }

    private static int getGrayValue(int color) {
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);
        return (r + g + b) / 3;
    }

    /**
     * 粗匹配特征点
     */
    private static List<Point> findRoughMatches(int[][] source, int[][] template,
                                                int sourceWidth, int templateWidth) {
        List<Point> matches = new ArrayList<>();
        int templateHeight = template[0].length;

        // 简化版特征匹配（实际项目应考虑使用ORB/SIFT等算法）
        for (int y = 0; y <= source[0].length - templateHeight; y++) {
            for (int x = 0; x <= sourceWidth - templateWidth; x++) {
                int matchScore = 0;

                // 计算特征相似度
                for (int ty = 0; ty < templateHeight; ty++) {
                    for (int tx = 0; tx < templateWidth; tx++) {
                        int diff = Math.abs(source[x+tx][y+ty] - template[tx][ty]);
                        matchScore += (100 - diff); // 差异越小分数越高
                    }
                }

                // 如果匹配分数高于阈值，认为是候选点
                if (matchScore > templateWidth * templateHeight * 60) {
                    matches.add(new Point(x, y));
                }
            }
        }
        return matches;
    }

    /**
     * 调整图像大小
     */
    private static Bitmap resizeBitmap(Bitmap source, int newWidth, int newHeight) {
        return Bitmap.createScaledBitmap(source, newWidth, newHeight, true);
    }

    /**
     * 直方图比较（优化版）
     */
    private static double compareByHistogram(Bitmap bmp1, Bitmap bmp2) {
        // 实现同前，但使用更小的直方图bins提高效率
        int[] hist1 = new int[64];
        int[] hist2 = new int[64];

        // 简化的直方图计算
        for (int y = 0; y < bmp1.getHeight(); y++) {
            for (int x = 0; x < bmp1.getWidth(); x++) {
                int gray1 = getGrayValue(bmp1.getPixel(x, y));
                int gray2 = getGrayValue(bmp2.getPixel(x, y));
                hist1[gray1/4]++;
                hist2[gray2/4]++;
            }
        }

        // 计算相似度
        double sum = 0, sum1 = 0, sum2 = 0;
        for (int i = 0; i < hist1.length; i++) {
            sum += hist1[i] * hist2[i];
            sum1 += hist1[i] * hist1[i];
            sum2 += hist2[i] * hist2[i];
        }

        return sum / (Math.sqrt(sum1) * Math.sqrt(sum2));
    }
}